/**
 @Name :laytpl 模板引擎
 @License：MIT
 @ KuoTpl
Mode("TPL").Render( 可以是html模版 | @config文件夹下的html不要带后缀,数据);
模版语法
语法	说明	示例
{{ KUO.field }}	输出一个普通字段，不转义html	

{{= KUO.field }}	输出一个普通字段，并转义html	
{{# JavaScript表达式 }}	JS 语句。一般用于逻辑处理。用分隔符加 # 号开头。
注意：如果你是想输出一个函数，正确的写法是：{{ fn() }}，而不是：{{# fn() }}	
</>code
{{#  
  var fn = function(){
    return '2017-08-18';
  }; 
}}
 
{{#  if(true){ }}
  开始日期：{{ fn() }}
{{#  } else { }}
  已截止
{{#  } }}                
{{! template !}}	对一段指定的模板区域进行过滤，即不解析该区域的模板。
</>code
<div> {{! 这里面的模板不会被解析  !}}</div>
 */
var Kuo_TPL = {
    COpen:"{{",
    CClose:"}}",
    CaChe:{},
    Config:async (config)=>{
        if(config){
            if(config.open){
                Kuo_TPL.COpen = config.open;
            }
            if(config.close){
                Kuo_TPL.CClose = config.close;
            }
        }
        return Kuo_TPL;
    },Error: function(e, tplog){
        return e + ' '+ (tplog || '');
    },EXP: function(str){
        return new RegExp(str, 'g');
    },Query: function(type, _, __){
        var types = ['#([\\s\\S])+?', '([^{#}])*?' ][type || 0];
        return Kuo_TPL.EXP((_||'') + Kuo_TPL.COpen + types + Kuo_TPL.CClose + (__||''));
    },Escape: function(html){
        return String(html||'').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;').replace(/"/g, '&quot;');
    },Flush:function(){
        Kuo_TPL.CaChe ={};
        return true;
    },Render:async function(tpl,data,THIS){
        var tplog = tpl;
        if(tpl.charAt(0) == "@"){
            var tplfile = tpl.slice(1, tpl.length);
            tplfile = Mode("Tools").GUoLV(tplfile);
            if(!Kuo_TPL.CaChe[tplfile] || Debug ){
                try {
                    tpl = FS.readFileSync(TPL+tplfile+".html").toString();
                    Kuo_TPL.CaChe[tplfile] = tpl;
                } catch (err) {
                    return Kuo_TPL.Error("file does not exist ", "/config/"+tplfile+".html");
                }
            }else{
                tpl = Kuo_TPL.CaChe[tplfile];
            }
        }
        var jss = Kuo_TPL.EXP('^'+Kuo_TPL.COpen+'#', ''), jsse = Kuo_TPL.EXP(Kuo_TPL.CClose+'$', '');
        tpl = tpl.replace(/\s+|\r|\t|\n/g, ' ')
            .replace(Kuo_TPL.EXP(Kuo_TPL.COpen+'#'), Kuo_TPL.COpen+'# ')
            .replace(Kuo_TPL.EXP(Kuo_TPL.CClose+'}'), '} '+Kuo_TPL.CClose).replace(/\\/g, '\\\\')
            //不匹配指定区域的内容
            .replace(Kuo_TPL.EXP(Kuo_TPL.COpen + '!(.+?)!' + Kuo_TPL.CClose), function(str){
                str = str.replace(Kuo_TPL.EXP('^'+ Kuo_TPL.COpen + '!'), '')
                .replace(Kuo_TPL.EXP('!'+ Kuo_TPL.CClose), '')
                .replace(Kuo_TPL.EXP(Kuo_TPL.COpen + '|' + Kuo_TPL.CClose), function(tag){
                    return tag.replace(/(.)/g, '\\$1')
                });
                return str
            })
            //匹配JS规则内容
            .replace(/(?="|')/g, '\\').replace(Kuo_TPL.Query(), function(str){
                str = str.replace(jss, '').replace(jsse, '');
                return '";' + str.replace(/\\(.)/g, '$1') + ';VIEW+="';
            })
            //匹配普通字段
            .replace(Kuo_TPL.Query(1), function(str){
                var start = '"+(';
                if(str.replace(/\s/g, '') === Kuo_TPL.COpen+Kuo_TPL.CClose){
                    return '';
                }
                str = str.replace(Kuo_TPL.EXP(Kuo_TPL.COpen+'|'+Kuo_TPL.CClose), '');
                if(/^=/.test(str)){
                    str = str.replace(/^=/, '');
                    start = '"+_KUOTPL_(';
                }
                return start + str.replace(/\\(.)/g, '$1') + ')+"';
            });

        tpl = '"use strict";var VIEW = "' + tpl + '";return VIEW;';
        
        try{
            var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
            tpl =  new AsyncFunction('KUO, _KUOTPL_,THIS', tpl);
            return   tpl(data, Kuo_TPL.Escape,THIS);
        } catch(e){
            return Kuo_TPL.Error(e, tplog);
        }
    }
};
module.exports =  Kuo_TPL;